home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume22 / oraperl / patch02 next >
Encoding:
Text File  |  1991-08-25  |  32.0 KB  |  1,095 lines

  1. Newsgroups: comp.sources.misc
  2. From: Kevin Stock <kstock@gouldfr.encore.fr>
  3. Subject:  v22i058:  oraperl - Extensions to Perl to access Oracle databases, Patch02
  4. Message-ID: <1991Aug25.221731.11703@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 37178088c22c90a03082382d6d36b805
  6. Date: Sun, 25 Aug 1991 22:17:31 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Kevin Stock <kstock@gouldfr.encore.fr>
  10. Posting-number: Volume 22, Issue 58
  11. Archive-name: oraperl/patch02
  12. Environment: Perl, Oracle, Pro*C
  13. Patch-To: oraperl: Volume 18, Issue 10
  14.  
  15. Oraperl is a set of usersubs for Perl which allow scripts to access Oracle 
  16. databases. You need Perl v3.0.27 or later and Oracle Pro*C to build it.
  17. Oraperl appeared in comp.sources.misc in April 1991 (v18i010), and the first
  18. patch appeared there in July 1991 (v20i097).
  19.  
  20. This patch does the following:
  21.  
  22.     Adds support for dynamically modifiable SQL statements
  23.     Adds a Hints file explaining problems which have arisen
  24.     Corrects an error in the quick-reference sheet
  25.  
  26. To apply, please unshar this message, which will create the files Hints,
  27. Patch02, colons.c and mkdb.pl Then feed Patch02 into the patch program.
  28. Modify the Makefile as required for your installation and run make.
  29.  
  30. Thanks to all those who have notified me of problems or suggested improvements,
  31. or even just boosted my ego by telling me that you're using it.
  32.  
  33. Please let me know if you have any problems, comments or bug-fixes.
  34.  
  35.   ,---------------.
  36. ,-+-------------. |    Kevin Stock
  37. | | E N C O R E | |    kstock@gouldfr.encore.fr
  38. | `-------------+-'
  39. `---------------'
  40. ---------
  41. #!/bin/sh
  42. # This is a shell archive (produced by shar 3.49)
  43. # To extract the files from this archive, save it to a file, remove
  44. # everything above the "!/bin/sh" line above, and type "sh file_name".
  45. #
  46. # made 08/23/1991 07:22 UTC by kstock@mmcompta
  47. # Source directory /usr/local/src/cmd/oraperl
  48. #
  49. # existing files will NOT be overwritten unless -c is specified
  50. #
  51. # This shar contains:
  52. # length  mode       name
  53. # ------ ---------- ------------------------------------------
  54. #   1785 -rw-r--r-- Hints
  55. #  23937 -rw-r--r-- Patch02
  56. #    830 -rw-r--r-- colons.c
  57. #   1444 -rwxr-xr-x mkdb.pl
  58. #
  59. # ============= Hints ==============
  60. if test -f 'Hints' -a X"$1" != X"-c"; then
  61.     echo 'x - skipping Hints (File already exists)'
  62. else
  63. echo 'x - extracting Hints (Text)'
  64. sed 's/^X//' << 'SHAR_EOF' > 'Hints' &&
  65. X
  66. XThis file contains hints and tips about Oraperl, dealing with problems which
  67. Xhave arisen in the past.
  68. X
  69. X
  70. XRetrieving Dates
  71. X================
  72. X
  73. XIf you want to retrieve a field which is declared as an Oracle DATE, then you
  74. Xmust explicitly format it using the SQL*Plus TO_CHAR function, for example:
  75. X
  76. X    $csr = &ora_open($lda, "select to_char(sysdate, 'DD/MM/YY') from dual")
  77. X
  78. XOtherwise, Oracle tells Oraperl that the field only occupies seven bytes,
  79. Xand a truncation error occurs when the field is fetched. This causes
  80. X&ora_fetch() to return an error.
  81. X
  82. XI hope to correct this in a future patch.
  83. X
  84. X
  85. XBuilding on a Convex machine
  86. X============================
  87. X
  88. XThe  strtol()  function used at the start of most of the functions in orafns.c
  89. Xand in oracle.mus must be replaced by  strtoul() to allow larger addresses to
  90. Xbe converted.
  91. X
  92. XThe  putenv()  function used in  set_sid()  must be replaced by  setenv() .
  93. X
  94. X
  95. XUsing Bind Variables
  96. X====================
  97. X
  98. XThe support for bind variables does not reflect the full potential of Pro*C.
  99. X
  100. XFirstly, bind variables may only be numeric; named bind variables are not
  101. Xsupported. They must run in sequence from 1. (This is to make it easy for
  102. X&ora_bind() to check that it has received the correct number of parameters.)
  103. X
  104. XSecondly, they may only be used to modify values within the SQL statement,
  105. Xnot field or table names. Thus
  106. X
  107. X    insert into telno values (:1, :2)
  108. X
  109. Xis valid, but
  110. X
  111. X    select * from telno order by :1
  112. X
  113. Xis not. This made the interaction between &ora_open() and &ora_bind() simpler,
  114. Xbut if it's a serious restriction for you let me know, and I'll look into
  115. Xextending it. (Of course, there's nothing to stop you doing:
  116. X
  117. X    $order_by = "name";
  118. X    &ora_open($lda, "select * from telno order by $order_by");
  119. X
  120. Xso I don't think it should be too big a problem.)
  121. SHAR_EOF
  122. chmod 0644 Hints ||
  123. echo 'restore of Hints failed'
  124. Wc_c="`wc -c < 'Hints'`"
  125. test 1785 -eq "$Wc_c" ||
  126.     echo 'Hints: original size 1785, current size' "$Wc_c"
  127. fi
  128. # ============= Patch02 ==============
  129. if test -f 'Patch02' -a X"$1" != X"-c"; then
  130.     echo 'x - skipping Patch02 (File already exists)'
  131. else
  132. echo 'x - extracting Patch02 (Text)'
  133. sed 's/^X//' << 'SHAR_EOF' > 'Patch02' &&
  134. Xdiff -c /user/mis/kstock/tmp/CHANGES ./CHANGES
  135. X*** /user/mis/kstock/tmp/CHANGES    Fri Aug 23 08:50:45 1991
  136. X--- ./CHANGES    Fri Aug 23 09:10:27 1991
  137. X***************
  138. X*** 8,10 ****
  139. X--- 8,16 ----
  140. X  Added network addresses to the manual pages
  141. X  Added a PATCHLEVEL file
  142. X  No functional changes
  143. X+ 
  144. X+ Patch 02
  145. X+ ========
  146. X+ Added support for dynamically modifiable SQL statements
  147. X+ Added a Hints file
  148. X+ Corrected an error in the quick-reference sheet
  149. Xdiff -c /user/mis/kstock/tmp/Makefile ./Makefile
  150. X*** /user/mis/kstock/tmp/Makefile    Fri Aug 23 08:50:56 1991
  151. X--- ./Makefile    Mon Aug  5 11:01:38 1991
  152. X***************
  153. X*** 3,9 ****
  154. X  # Change these to your ORACLE installation directory and Perl source directory
  155. X  
  156. X  ORACLE_HOME    = /usr/soft/oracle
  157. X! SRC        = /usr/soft/public/perl_4.0.09
  158. X  
  159. X  # Oracle Definitions, taken from proc.mk
  160. X  
  161. X--- 3,9 ----
  162. X  # Change these to your ORACLE installation directory and Perl source directory
  163. X  
  164. X  ORACLE_HOME    = /usr/soft/oracle
  165. X! SRC        = /usr/soft/public/perl_4.0.10
  166. X  
  167. X  # Oracle Definitions, taken from proc.mk
  168. X  
  169. X***************
  170. X*** 27,48 ****
  171. X  DEBUG        = -DPERL_DEBUGGING
  172. X  CFLAGS        = $(DEBUG) -I$(SRC) $(GLOBINCS) -O
  173. X  
  174. X! oraperl: $(SRC)/uperl.o usersub.o oracle.o orafns.o getcursor.o
  175. X!     cc -o oraperl $(SRC)/uperl.o usersub.o oracle.o orafns.o getcursor.o \
  176. X!         -lm $(OCILIB) $(NETLIBS) $(ORALIBS) $(CLIBS) $(LIBS)
  177. X  
  178. X  oracle.c: $(SRC)/usub/mus oracle.mus
  179. X-     chmod +x $(SRC)/usub/mus
  180. X      $(SRC)/usub/mus oracle.mus >oracle.c
  181. X  
  182. X! usersub.o oracle.o orafns.o getcursor.o:    orafns.h
  183. X! 
  184. X! print:    Makefile orafns.h orafns.c oracle.mus usersub.c getcursor.c
  185. X!     pr -fn Makefile orafns.h getcursor.c orafns.c oracle.mus usersub.c | \
  186. X!         pr -fto4 -e > Print
  187. X! 
  188. X! man: oraperl.1
  189. X!     nroff -man oraperl.1 >oraperl.man
  190. X  
  191. X  clean:
  192. X      rm -f nohup.out oraperl *.o oracle.c oraperl.man Print tags out core
  193. X--- 27,44 ----
  194. X  DEBUG        = -DPERL_DEBUGGING
  195. X  CFLAGS        = $(DEBUG) -I$(SRC) $(GLOBINCS) -O
  196. X  
  197. X! SRCS        = usersub.c oracle.c orafns.c getcursor.c colons.c
  198. X! OBJS        = usersub.o oracle.o orafns.o getcursor.o colons.o
  199. X! HDRS        = orafns.h
  200. X! 
  201. X! oraperl: $(SRC)/uperl.o $(OBJS)
  202. X!     cc -o oraperl $(SRC)/uperl.o $(OBJS)                \
  203. X!           -lm $(OCILIB) $(NETLIBS) $(ORALIBS) $(CLIBS) $(LIBS)
  204. X  
  205. X  oracle.c: $(SRC)/usub/mus oracle.mus
  206. X      $(SRC)/usub/mus oracle.mus >oracle.c
  207. X  
  208. X! $(OBJS):    $(HDRS)
  209. X  
  210. X  clean:
  211. X      rm -f nohup.out oraperl *.o oracle.c oraperl.man Print tags out core
  212. Xdiff -c /user/mis/kstock/tmp/Oracle-v5 ./Oracle-v5
  213. X*** /user/mis/kstock/tmp/Oracle-v5    Fri Aug 23 08:50:46 1991
  214. X--- ./Oracle-v5    Wed Aug  7 09:24:00 1991
  215. X***************
  216. X*** 20,28 ****
  217. X  >
  218. X  > LDFLAGS    = -L$(ORACLE_HOME)/c/libs -L$(ORACLE_HOME)/rdbms/libs
  219. X  >
  220. X! > oraperl: $(SRC)/uperl.o usersub.o oracle.o orafns.o getcursor.o
  221. X! >     $(CC) -o oraperl $(LDFLAGS) $(SRC)/uperl.o usersub.o oracle.o orafns.o \
  222. X! >         getcursor.o $(ORALIBS) $(LIBS)
  223. X  
  224. X  Second method - much simpler. Only seems to require the first two libraries
  225. X  (libocic and liboracle) of the previous method, but this time they live under
  226. X--- 20,27 ----
  227. X  >
  228. X  > LDFLAGS    = -L$(ORACLE_HOME)/c/libs -L$(ORACLE_HOME)/rdbms/libs
  229. X  >
  230. X! > oraperl: $(SRC)/uperl.o $(OBJS)
  231. X! >     $(CC) -o oraperl $(LDFLAGS) $(SRC)/uperl.o $(OBJS) $(ORALIBS) $(LIBS)
  232. X  
  233. X  Second method - much simpler. Only seems to require the first two libraries
  234. X  (libocic and liboracle) of the previous method, but this time they live under
  235. Xdiff -c /user/mis/kstock/tmp/PATCHLEVEL ./PATCHLEVEL
  236. X*** /user/mis/kstock/tmp/PATCHLEVEL    Fri Aug 23 08:50:47 1991
  237. X--- ./PATCHLEVEL    Mon Aug  5 11:01:39 1991
  238. X***************
  239. X*** 1 ****
  240. X! 1
  241. X--- 1 ----
  242. X! 2
  243. Xdiff -c /user/mis/kstock/tmp/README ./README
  244. X*** /user/mis/kstock/tmp/README    Fri Aug 23 08:50:56 1991
  245. X--- ./README    Fri Aug 23 08:53:04 1991
  246. X***************
  247. X*** 24,30 ****
  248. X  be changed to  str_2static()  with the same arguments.
  249. X  
  250. X  I've only tested this on an Encore Multimax 520 running UMAX V (Sys Vr3.2),
  251. X! using Perl 3.0.34, 4.0.00 4.0.03 and 4.0.09 with Oracle version 6, as I don't
  252. X  have access to any other system with Pro*C. I'd appreciate any comments,
  253. X  bug-reports etc.
  254. X  
  255. X--- 24,30 ----
  256. X  be changed to  str_2static()  with the same arguments.
  257. X  
  258. X  I've only tested this on an Encore Multimax 520 running UMAX V (Sys Vr3.2),
  259. X! using Perl 3.0.34, 4.0.00 4.0.03 and 4.0.10 with Oracle version 6, as I don't
  260. X  have access to any other system with Pro*C. I'd appreciate any comments,
  261. X  bug-reports etc.
  262. X  
  263. X***************
  264. X*** 37,52 ****
  265. X      getcursor.c    functions to deal with the cursor pool
  266. X      orafns.c    actual functions to interact with oracle
  267. X      usersub.c    initialisation routine
  268. X  
  269. X! Examples (taken from the manual page)
  270. X      debug-p        tests to see if debugging is available
  271. X      ex.pl        simple example of using the functions
  272. X  
  273. X  Documentation
  274. X      oraperl.doc    explains some of the thinking behind Oraperl
  275. X      oraperl.ref    quick reference (troff format)
  276. X      oraperl.1    manual page
  277. X      Oracle-v5    Hints for compiling Oraperl with Oracle v5
  278. X  
  279. X  Many thanks to Larry for Perl. Now if only we could get the Camel book
  280. X  into France! Hmm. Any plans for "Le Livre Chameau"?
  281. X--- 37,59 ----
  282. X      getcursor.c    functions to deal with the cursor pool
  283. X      orafns.c    actual functions to interact with oracle
  284. X      usersub.c    initialisation routine
  285. X+     colons.c    counts substitution variables in a statement
  286. X  
  287. X! Examples
  288. X      debug-p        tests to see if debugging is available
  289. X      ex.pl        simple example of using the functions
  290. X+     mkdb.pl        more extensive example, showing the use of ora_bind()
  291. X  
  292. X  Documentation
  293. X      oraperl.doc    explains some of the thinking behind Oraperl
  294. X      oraperl.ref    quick reference (troff format)
  295. X      oraperl.1    manual page
  296. X+     Hints        notes on using oraperl
  297. X      Oracle-v5    Hints for compiling Oraperl with Oracle v5
  298. X+ 
  299. X+ Miscellaneous
  300. X+     CHANGES        Summary of changes to Oraperl
  301. X+     PATCHLEVEL    current patchlevel (2)
  302. X  
  303. X  Many thanks to Larry for Perl. Now if only we could get the Camel book
  304. X  into France! Hmm. Any plans for "Le Livre Chameau"?
  305. Xdiff -c /user/mis/kstock/tmp/getcursor.c ./getcursor.c
  306. X*** /user/mis/kstock/tmp/getcursor.c    Fri Aug 23 08:50:57 1991
  307. X--- ./getcursor.c    Mon Aug  5 11:01:39 1991
  308. X***************
  309. X*** 269,275 ****
  310. X   {
  311. X      DEBUG(8, (fprintf(stderr, "check_csr(%#lx)\n", (long) csr)));
  312. X  
  313. X!     if (ora_findcursor(csr) && (csr->hda == NULL) && (csr->data != NULL))
  314. X      {
  315. X          DEBUG(8, (fputs("check_csr: valid\n", stderr)));
  316. X          return (1);
  317. X--- 269,275 ----
  318. X   {
  319. X      DEBUG(8, (fprintf(stderr, "check_csr(%#lx)\n", (long) csr)));
  320. X  
  321. X!     if (ora_findcursor(csr) && (csr->hda == NULL))
  322. X      {
  323. X          DEBUG(8, (fputs("check_csr: valid\n", stderr)));
  324. X          return (1);
  325. Xdiff -c /user/mis/kstock/tmp/oracle.mus ./oracle.mus
  326. X*** /user/mis/kstock/tmp/oracle.mus    Fri Aug 23 08:50:57 1991
  327. X--- ./oracle.mus    Mon Aug  5 11:01:39 1991
  328. X***************
  329. X*** 25,30 ****
  330. X--- 25,31 ----
  331. X  static enum usersubs {
  332. X      US_ora_login,
  333. X      US_ora_open,
  334. X+     US_ora_bind,
  335. X      US_ora_fetch,
  336. X      US_ora_close,
  337. X      US_ora_logoff,
  338. X***************
  339. X*** 53,58 ****
  340. X--- 54,60 ----
  341. X  
  342. X      make_usub("ora_login",    US_ora_login,    usersub, filename);
  343. X      make_usub("ora_open",    US_ora_open,    usersub, filename);
  344. X+     make_usub("ora_bind",    US_ora_bind,    usersub, filename);
  345. X      make_usub("ora_fetch",    US_ora_fetch,    usersub, filename);
  346. X      make_usub("ora_close",    US_ora_close,    usersub, filename);
  347. X      make_usub("ora_logoff",    US_ora_logoff,    usersub, filename);
  348. X***************
  349. X*** 115,120 ****
  350. X--- 117,148 ----
  351. X      }
  352. X      /* NOTREACHED */
  353. X  
  354. X+     case US_ora_bind:
  355. X+     if (items < 2)
  356. X+         fatal("Usage: &ora_bind($csr, $var ...)");
  357. X+     else {
  358. X+         char *csr        = (char *) str_get(st[1]);
  359. X+         char **vars        = (char **) malloc((items-1) * sizeof(char *));
  360. X+         int i, retval;
  361. X+ 
  362. X+         if (vars == NULL)
  363. X+         {
  364. X+         ora_errno = ORAP_NOMEM;
  365. X+         retval = 0;
  366. X+         }
  367. X+         else
  368. X+         {
  369. X+         for (i = 0 ; i < items - 1 ; i++)
  370. X+         {
  371. X+             vars[i] = (char *) str_get(st[i+2]);
  372. X+         }
  373. X+         retval = ora_bind(csr, vars, items - 1);
  374. X+         }
  375. X+ 
  376. X+         str_numset(st[0], (double) retval);
  377. X+     }
  378. X+     return sp;
  379. X+ 
  380. X  CASE    char *    ora_close
  381. X  I    char *    csr
  382. X  END
  383. X***************
  384. X*** 202,207 ****
  385. X--- 230,243 ----
  386. X  
  387. X              case ORAP_NOSID:
  388. X                  str_set(str, "couldn't set ORACLE_SID");
  389. X+                 break;
  390. X+ 
  391. X+             case ORAP_BADVAR:
  392. X+                 str_set(str, "bad colon variable sequence");
  393. X+                 break;
  394. X+ 
  395. X+             case ORAP_NUMVARS:
  396. X+                 str_set(str, "wrong number of variables");
  397. X                  break;
  398. X  
  399. X              default:
  400. Xdiff -c /user/mis/kstock/tmp/orafns.c ./orafns.c
  401. X*** /user/mis/kstock/tmp/orafns.c    Fri Aug 23 08:50:57 1991
  402. X--- ./orafns.c    Mon Aug  5 11:01:40 1991
  403. X***************
  404. X*** 186,199 ****
  405. X  }
  406. X  
  407. X  
  408. X! /* ora_open(lda, query)
  409. X   *
  410. X!  * sets and executes the specified sql query
  411. X   */
  412. X  
  413. X! char *ora_open(lda_s, query)
  414. X  char *lda_s;
  415. X! char *query;
  416. X  {
  417. X      int i;
  418. X      struct cursor *csr;
  419. X--- 186,199 ----
  420. X  }
  421. X  
  422. X  
  423. X! /* ora_open(lda, stmt)
  424. X   *
  425. X!  * sets and executes the specified sql statement
  426. X   */
  427. X  
  428. X! char *ora_open(lda_s, stmt)
  429. X  char *lda_s;
  430. X! char *stmt;
  431. X  {
  432. X      int i;
  433. X      struct cursor *csr;
  434. X***************
  435. X*** 200,206 ****
  436. X      struct cursor *lda = (struct cursor *) strtol(lda_s, (char **) NULL, 0);
  437. X      short dbsize;
  438. X  
  439. X!     DEBUG(8, (fprintf(stderr, "ora_open(%#lx, %s)\n", (long) lda, query)));
  440. X  
  441. X      if (check_lda(lda) == 0)
  442. X      {
  443. X--- 200,206 ----
  444. X      struct cursor *lda = (struct cursor *) strtol(lda_s, (char **) NULL, 0);
  445. X      short dbsize;
  446. X  
  447. X!     DEBUG(8, (fprintf(stderr, "ora_open(%#lx, %s)\n", (long) lda, stmt)));
  448. X  
  449. X      if (check_lda(lda) == 0)
  450. X      {
  451. X***************
  452. X*** 216,224 ****
  453. X          return((char *) NULL);
  454. X      }
  455. X  
  456. X      if ((oopen(csr->csr, lda->csr, (char *)-1, -1, -1, (char *)-1, -1) != 0)
  457. X!         || (osql3(csr->csr, query, -1) != 0)
  458. X!         || (oexec(csr->csr) != 0))
  459. X      {
  460. X          ora_errno = csr->csr->csrrc;
  461. X          ora_dropcursor(csr);
  462. X--- 216,238 ----
  463. X          return((char *) NULL);
  464. X      }
  465. X  
  466. X+     /* Check whether there are any substitution variables in the statement
  467. X+      * If there are, we don't execute the statement yet.
  468. X+      */
  469. X+     if ((csr->varfields = count_colons(stmt)) < 0)
  470. X+     {
  471. X+         DEBUG(8, (fputs("ora_open: invalid variable sequence\n",
  472. X+             stderr)));
  473. X+         ora_errno = ORAP_BADVAR;
  474. X+         return((char *) NULL);
  475. X+     }
  476. X+ 
  477. X+     DEBUG(8, (fprintf(stderr,
  478. X+         "ora_open: statement contains %d colons\n", csr->varfields)));
  479. X+ 
  480. X      if ((oopen(csr->csr, lda->csr, (char *)-1, -1, -1, (char *)-1, -1) != 0)
  481. X!         || (osql3(csr->csr, stmt, -1) != 0)
  482. X!         || ((csr->varfields == 0) && (oexec(csr->csr) != 0)))
  483. X      {
  484. X          ora_errno = csr->csr->csrrc;
  485. X          ora_dropcursor(csr);
  486. X***************
  487. X*** 239,274 ****
  488. X  
  489. X      ora_errno = 0;
  490. X  
  491. X!     if ((csr->data = (char **) malloc(i * sizeof(char *))) == NULL)
  492. X!     {
  493. X!         DEBUG(128, (fputs("ora_open: out of memory\n", stderr)));
  494. X!         DEBUG(8, (fputs("ora_open: returning NOMEM\n", stderr)));
  495. X!         ora_errno = ORAP_NOMEM;
  496. X!         ora_dropcursor(csr);
  497. X!         return(0);
  498. X!     }
  499. X!     DEBUG(128, (fprintf(stderr, "ora_open: got data at %#lx\n",csr->data)));
  500. X!     csr->nfields = i;
  501. X! 
  502. X!     for (i = 0 ; i < csr->nfields ; i++)
  503. X      {
  504. X!         odsc(csr->csr, i + 1, &dbsize, (short *) 0, (short *) 0,
  505. X!             (short *) 0, (char *) 0, (short *) 0, (short *) 0);
  506. X! 
  507. X!         if ((csr->data[i] = (char *) malloc(dbsize + 1)) == NULL)
  508. X          {
  509. X-             csr->nfields = i;
  510. X-             ora_dropcursor(csr);
  511. X- 
  512. X              DEBUG(128, (fputs("ora_open: out of memory\n",stderr)));
  513. X              DEBUG(8, (fputs("ora_open: returning NOMEM\n",stderr)));
  514. X              ora_errno = ORAP_NOMEM;
  515. X!             return((char *) NULL);
  516. X          }
  517. X!         DEBUG(128, (fprintf(stderr, "ora_open: got field %d at %#lx\n",
  518. X!             i, csr->data[i])));
  519. X!         odefin(csr->csr, i + 1, csr->data[i], dbsize + 1, 5, 0,
  520. X!             (short *) 0, (char *) 0, 0, 0, (short *) 0, (char *) 0);
  521. X      }
  522. X  
  523. X      sprintf(address, "%#lx", (long) csr);
  524. X--- 253,300 ----
  525. X  
  526. X      ora_errno = 0;
  527. X  
  528. X!     if (i > 0)
  529. X      {
  530. X!         if ((csr->data = (char **) malloc(i * sizeof(char *))) == NULL)
  531. X          {
  532. X              DEBUG(128, (fputs("ora_open: out of memory\n",stderr)));
  533. X              DEBUG(8, (fputs("ora_open: returning NOMEM\n",stderr)));
  534. X              ora_errno = ORAP_NOMEM;
  535. X!             ora_dropcursor(csr);
  536. X!             return(0);
  537. X!         }
  538. X!         DEBUG(128, (fprintf(stderr,
  539. X!             "ora_open: got data at %#lx\n",csr->data)));
  540. X!         csr->nfields = i;
  541. X! 
  542. X!         for (i = 0 ; i < csr->nfields ; i++)
  543. X!         {
  544. X!             odsc(csr->csr, i + 1, &dbsize, (short *) 0, (short *) 0,
  545. X!                 (short *) 0, (char *) 0, (short *) 0, (short *) 0);
  546. X! 
  547. X!             if ((csr->data[i] = (char *) malloc(dbsize+1)) == NULL)
  548. X!             {
  549. X!                 csr->nfields = i;
  550. X!                 ora_dropcursor(csr);
  551. X!                 DEBUG(128, (fputs("ora_open: out of memory\n",
  552. X!                     stderr)));
  553. X!                 DEBUG(8, (fputs("ora_open: returning NOMEM\n",
  554. X!                     stderr)));
  555. X!                 ora_errno = ORAP_NOMEM;
  556. X!                 return((char *) NULL);
  557. X!             }
  558. X!             DEBUG(128, (fprintf(stderr,
  559. X!                 "ora_open: got field %d at %#lx\n",
  560. X!                 i, csr->data[i])));
  561. X!             odefin(csr->csr, i + 1, csr->data[i], dbsize + 1, 5, 0,
  562. X!                 (short *) 0, (char *) 0, 0, 0, (short *) 0,
  563. X!                 (char *) 0);
  564. X          }
  565. X!     }
  566. X!     else
  567. X!     {
  568. X!         DEBUG(128, (fputs("ora_open: no data to return\n", stderr)));
  569. X!         csr->data = NULL;
  570. X      }
  571. X  
  572. X      sprintf(address, "%#lx", (long) csr);
  573. X***************
  574. X*** 309,314 ****
  575. X--- 335,397 ----
  576. X      ora_errno = 0;
  577. X      DEBUG(8, (fprintf(stderr,"ora_fetch: returning <%d>\n", csr->nfields)));
  578. X      return(csr->nfields);
  579. X+ }
  580. X+ 
  581. X+ 
  582. X+ /* ora_bind(csr_s, vars, nitems)
  583. X+  *
  584. X+  * binds actual values to the SQL statement associated with csr
  585. X+  */
  586. X+ 
  587. X+ int ora_bind(csr_s, vars, nitems)
  588. X+ char *csr_s, **vars;
  589. X+ int nitems;
  590. X+ {
  591. X+     int i, ret;
  592. X+     struct cursor *csr = (struct cursor *) strtol(csr_s, (char **) NULL, 0);
  593. X+ 
  594. X+     DEBUG(8, (fprintf(stderr, "ora_bind(%#lx, %#lx, %d)\n",
  595. X+         (long) csr, (long) vars, nitems)));
  596. X+ 
  597. X+     if (check_csr(csr) == 0)
  598. X+     {
  599. X+         DEBUG(8, (fputs("ora_bind: returning 0\n", stderr)));
  600. X+         ora_errno = ORAP_INVCSR;
  601. X+         return(0);
  602. X+     }
  603. X+ 
  604. X+     if (csr->varfields != nitems)
  605. X+     {
  606. X+         DEBUG(8, (fprintf("ora_bind: expected %d items, got %d\n",
  607. X+             csr->varfields, nitems)));
  608. X+         ora_errno = ORAP_NUMVARS;
  609. X+         return(0);
  610. X+     }
  611. X+ 
  612. X+     for (i = 0 ; i < nitems ; i++)
  613. X+     {
  614. X+         if ((ret = obndrn(csr->csr, i+1, vars[i], strlen(vars[i])+1,
  615. X+             5, -1, (short *) -1, (char *) -1, 0, 0)) != 0)
  616. X+         {
  617. X+             ora_errno = csr->csr->csrrc;
  618. X+             DEBUG(8, (fputs("ora_bind: returning 0\n", stderr)));
  619. X+             return(0);
  620. X+         }
  621. X+ 
  622. X+         DEBUG(8, (fprintf(stderr, "ora_bind: obndrv %d %s OK\n",
  623. X+             i + 1, vars[i])));
  624. X+     }
  625. X+ 
  626. X+     if (oexec(csr->csr) != 0)
  627. X+     {
  628. X+         ora_errno = csr->csr->csrrc;
  629. X+         DEBUG(8, (fputs("ora_bind: returning 0\n", stderr)));
  630. X+         return(0);
  631. X+     }
  632. X+ 
  633. X+     DEBUG(8, (fputs("ora_bind: oexec successful\n", stderr)));
  634. X+     DEBUG(8, (fputs("ora_bind: returning 1\n", stderr)));
  635. X+     return(1);
  636. X  }
  637. X  
  638. X  
  639. Xdiff -c /user/mis/kstock/tmp/orafns.h ./orafns.h
  640. X*** /user/mis/kstock/tmp/orafns.h    Fri Aug 23 08:50:57 1991
  641. X--- ./orafns.h    Mon Aug  5 11:01:40 1991
  642. X***************
  643. X*** 17,23 ****
  644. X          *ora_close(),
  645. X          *ora_logoff();
  646. X  
  647. X! int         ora_fetch();
  648. X  
  649. X  
  650. X  /* These functions are internal to the system, not for public consumption */
  651. X--- 17,24 ----
  652. X          *ora_close(),
  653. X          *ora_logoff();
  654. X  
  655. X! int        ora_bind(),
  656. X!         ora_fetch();
  657. X  
  658. X  
  659. X  /* These functions are internal to the system, not for public consumption */
  660. X***************
  661. X*** 66,72 ****
  662. X      struct    csrdef    *csr;
  663. X      char        *hda,        /* used if this cursor is an lda     */
  664. X              **data;        /* used to receive database contents */
  665. X!     int        nfields;    /* number of fields to retrieve         */
  666. X      struct    cursor    *next;        /* list pointer                 */
  667. X  };
  668. X  
  669. X--- 67,74 ----
  670. X      struct    csrdef    *csr;
  671. X      char        *hda,        /* used if this cursor is an lda     */
  672. X              **data;        /* used to receive database contents */
  673. X!     int        nfields,    /* number of fields to retrieve         */
  674. X!             varfields;    /* number of modifiable variables    */
  675. X      struct    cursor    *next;        /* list pointer                 */
  676. X  };
  677. X  
  678. X***************
  679. X*** 73,78 ****
  680. X--- 75,81 ----
  681. X  
  682. X  /* functions that we use */
  683. X  
  684. X+ int    count_colons();
  685. X  long    strtol();
  686. X  char    *getenv(), *malloc();
  687. X  
  688. X***************
  689. X*** 125,131 ****
  690. X  
  691. X  #define    ORAP_ERRMIN    100000    /* lowest value allowed for an oraperl error */
  692. X  
  693. X! #define    ORAP_NOMEM    100001    /* out of memory        */
  694. X! #define    ORAP_INVCSR    100002    /* invalid cursor supplied    */
  695. X! #define    ORAP_INVLDA    100003    /* invalid lda supplied        */
  696. X! #define    ORAP_NOSID    100004    /* couldn't set ORACLE_SID    */
  697. X--- 128,136 ----
  698. X  
  699. X  #define    ORAP_ERRMIN    100000    /* lowest value allowed for an oraperl error */
  700. X  
  701. X! #define    ORAP_NOMEM    100001    /* out of memory            */
  702. X! #define    ORAP_INVCSR    100002    /* invalid cursor supplied        */
  703. X! #define    ORAP_INVLDA    100003    /* invalid lda supplied            */
  704. X! #define    ORAP_NOSID    100004    /* couldn't set ORACLE_SID        */
  705. X! #define    ORAP_BADVAR    100005    /* bad colon variable sequence        */
  706. X! #define    ORAP_NUMVARS    100006    /* wrong number of colon variables    */
  707. Xdiff -c /user/mis/kstock/tmp/oraperl.1 ./oraperl.1
  708. X*** /user/mis/kstock/tmp/oraperl.1    Fri Aug 23 08:50:58 1991
  709. X--- ./oraperl.1    Mon Aug  5 11:01:41 1991
  710. X***************
  711. X*** 8,13 ****
  712. X--- 8,14 ----
  713. X  .nf
  714. X  $lda = &ora_login($database, $name, $password)
  715. X  $csr = &ora_open($lda, $stmt)
  716. X+ &ora_bind($csr, $var, ...)
  717. X  &ora_fetch($csr)
  718. X  &ora_close($csr)
  719. X  &ora_logoff($lda)
  720. X***************
  721. X*** 26,33 ****
  722. X  using \fIora_login\fP.
  723. X  This is called with three parameters, 
  724. X  the system ID of the \fIOracle\fP database to be used,
  725. X- (which \fIOracle\fP products expect
  726. X- in the \fBORACLE_SID\fP environment variable)
  727. X  and the \fIOracle\fP username and password.
  728. X  The return value is a login identifier
  729. X  (an \fIORACLE Login Data Area\fP).
  730. X--- 27,32 ----
  731. X***************
  732. X*** 40,45 ****
  733. X--- 39,51 ----
  734. X  The return value is a statement identifier
  735. X  (an \fIORACLE cursor\fP).
  736. X  
  737. X+ If the SQL statement contains substitution variables
  738. X+ (see later)
  739. X+ \fIora_bind\fP is used to assign values to them.
  740. X+ This takes a statement identifier (obtained from \fIora_open\fP)
  741. X+ as its first parameter,
  742. X+ followed by as many parameters as are required by the statement.
  743. X+ 
  744. X  To retrieve the data returned from an \fISQL\fP \fBSELECT\fP statement,
  745. X  the program should make successive calls to \fIora_fetch\fP.
  746. X  This function takes a single parameter,
  747. X***************
  748. X*** 71,76 ****
  749. X--- 77,106 ----
  750. X  from the last function call, and
  751. X  \fIora_errstr\fP contains the \fIOracle\fP error message
  752. X  corresponding to the current value of \fIora_errno\fP.
  753. X+ .SH SUBSTITUTION VARIABLES
  754. X+ \fIOraperl\fP allows an SQL statement to contain substitution variables.
  755. X+ These consist of a colon (\fB:\fP) followed by a number.
  756. X+ For example, a program which added records to a telephone list
  757. X+ might use the following call to \fIora_open\fP:
  758. X+ 
  759. X+ .ti +.5i
  760. X+ \f(CW$csr = &ora_open($csr, "insert into phonelist values(:1, :2)");\fP
  761. X+ 
  762. X+ The two names \fB:1\fP and \fB:2\fP are called substitution variables.
  763. X+ The function \fIora_bind\fP is used to assign values to these variables.
  764. X+ For example, the following statements would add two new people to the list:
  765. X+ 
  766. X+ .ti +.5i
  767. X+ \f(CW&ora_bind($csr, "Annette", "472-8836");\fP
  768. X+ .ti +.5i
  769. X+ \f(CW&ora_bind($csr, "Brian", "937-1823");\fP
  770. X+ 
  771. X+ Note that the substitution variables must be assigned consecutively
  772. X+ beginning from \fB1\fP for each SQL statement,
  773. X+ as \fBora_bind()\fP assigns its parameters in this order.
  774. X+ Named substitution variables
  775. X+ (for example, \fB:NAME\fP, \fB:TELNO\fP)
  776. X+ are not permitted.
  777. X  .ne 28
  778. X  .SH EXAMPLE
  779. X  .if t .ft C
  780. X***************
  781. X*** 90,96 ****
  782. X  
  783. X  die ("You should use oraperl, not perl\n") unless defined &ora_login;
  784. X  
  785. X! $lda = &ora_login("t", "name", "password")
  786. X      || die $ora_errstr;
  787. X  $csr = &ora_open($lda, "select * from telno order by name")
  788. X      || die $ora_errstr;
  789. X--- 120,126 ----
  790. X  
  791. X  die ("You should use oraperl, not perl\n") unless defined &ora_login;
  792. X  
  793. X! $lda = &ora_login("t", "kstock", "kstock")
  794. X      || die $ora_errstr;
  795. X  $csr = &ora_open($lda, "select * from telno order by name")
  796. X      || die $ora_errstr;
  797. X***************
  798. X*** 151,157 ****
  799. X  \fIORACLE\fP by Oracle Corporation, California.
  800. X  .br
  801. X  \fIPerl\fP by Larry Wall, Netlabs
  802. X! (\f(CWlwall@netlabs.com\fP, \f(CWlwall@netlabs.com\fP).
  803. X  .br
  804. X  \fIOraperl\fP by Kevin Stock, Encore Computer SA, France
  805. X  (\f(CWkstock@gouldfr.encore.fr\fP).
  806. X--- 181,187 ----
  807. X  \fIORACLE\fP by Oracle Corporation, California.
  808. X  .br
  809. X  \fIPerl\fP by Larry Wall, Netlabs
  810. X! (\f(CWlwall@netlabs.com\fP).
  811. X  .br
  812. X  \fIOraperl\fP by Kevin Stock, Encore Computer SA, France
  813. X  (\f(CWkstock@gouldfr.encore.fr\fP).
  814. Xdiff -c /user/mis/kstock/tmp/oraperl.doc ./oraperl.doc
  815. X*** /user/mis/kstock/tmp/oraperl.doc    Fri Aug 23 08:50:23 1991
  816. X--- ./oraperl.doc    Mon Aug  5 11:01:41 1991
  817. X***************
  818. X*** 27,33 ****
  819. X  because it requires fixed addresses to be specified for receipt of data.
  820. X  A new interface was therefore created for \fBOraperl\fP.
  821. X  
  822. X! The interface follows the idiom of the following five tasks:
  823. X  
  824. X  .in +5
  825. X  .ta .4i 4.4i
  826. X--- 27,33 ----
  827. X  because it requires fixed addresses to be specified for receipt of data.
  828. X  A new interface was therefore created for \fBOraperl\fP.
  829. X  
  830. X! The interface follows the idiom of the following six tasks:
  831. X  
  832. X  .in +5
  833. X  .ta .4i 4.4i
  834. X***************
  835. X*** 34,51 ****
  836. X  .nf
  837. X  \fBTask        Interface\fP
  838. X  
  839. X! \fB1\fP    log in to the database    ora_login
  840. X! \fB2\fP    open a stream for an SQL statement    ora_open
  841. X! \fB3\fP    get the data    ora_fetch
  842. X! \fB4\fP    close the stream    ora_close
  843. X! \fB5\fP    log off of the database    ora_logoff
  844. X  .fi
  845. X  .in -5
  846. X  
  847. X- Steps \fB2\fP and \fB3\fP are kept separate
  848. X- because a single query may produce a large amount of data.
  849. X  
  850. X- 
  851. X  .ce 2
  852. X  \fBCursors\fP
  853. X  _______
  854. X--- 34,49 ----
  855. X  .nf
  856. X  \fBTask        Interface\fP
  857. X  
  858. X! \fB1\fP    log in to the database    \fIora_login\fP
  859. X! \fB2\fP    open a stream for an SQL statement    \fIora_open\fP
  860. X! \fB3\fP    modify the statement    \fIora_bind\fP
  861. X! \fB4\fP    get the data    \fIora_fetch\fP
  862. X! \fB5\fP    close the stream    \fIora_close\fP
  863. X! \fB6\fP    log off of the database    \fIora_logoff\fP
  864. X  .fi
  865. X  .in -5
  866. X  
  867. X  
  868. X  .ce 2
  869. X  \fBCursors\fP
  870. X  _______
  871. X***************
  872. X*** 96,103 ****
  873. X  
  874. X  Requests a cursor (\fIcsr\fP)
  875. X  and calls \fBOCI\ oopen\fP to connect it the the specified \fIlda\fP.
  876. X! It then calls \fBOCI\ osql3\fP to attach the SQL statement
  877. X! and \fBOCI\ oexec\fP to instruct \fIOracle\fP to execute it.
  878. X  
  879. X  If these three steps succeed,
  880. X  \fBora_open\fP then makes successive calls to \fBOCI\ odsc\fP
  881. X--- 94,102 ----
  882. X  
  883. X  Requests a cursor (\fIcsr\fP)
  884. X  and calls \fBOCI\ oopen\fP to connect it the the specified \fIlda\fP.
  885. X! It then calls \fBOCI\ osql3\fP to attach the SQL statement.
  886. X! If the statement does not contain any substitution variables,
  887. X! \fIora_open\fP calls \fBOCI\ oexec\fP to instruct \fIOracle\fP to execute it.
  888. X  
  889. X  If these three steps succeed,
  890. X  \fBora_open\fP then makes successive calls to \fBOCI\ odsc\fP
  891. X***************
  892. X*** 105,110 ****
  893. X--- 104,118 ----
  894. X  It allocates memory for these fields within \fIcsr\fP
  895. X  and attaches them to the cursor using \fBOCI\ odefin\fP.
  896. X  It returns the address of the \fIcsr\fP.
  897. X+ 
  898. X+ 
  899. X+ \fBora_bind(csr, var, ...)\fP
  900. X+ 
  901. X+ Binds the specified \fIvar\fPs to the substitution variables
  902. X+ in the SQL statement identified by \fIcsr\fP
  903. X+ and calls \fBOCI\ oexec\fP to execute the resulting statement.
  904. X+ Assumes that the substitution variables are \fB:1\fP, \fB:2\fP, \fB:3\fP, etc
  905. X+ in the order that they appear in the \fBora_bind\fP call.
  906. X  
  907. X  
  908. X  \fBora_fetch(csr)\fP
  909. Xdiff -c /user/mis/kstock/tmp/oraperl.ref ./oraperl.ref
  910. X*** /user/mis/kstock/tmp/oraperl.ref    Fri Aug 23 08:50:24 1991
  911. X--- ./oraperl.ref    Mon Aug  5 11:01:41 1991
  912. X***************
  913. X*** 17,25 ****
  914. X  Returns an \fIlda\fP for use with \fIora_open()\fP.
  915. X  .sp
  916. X  .ti -2m
  917. X! \fB$csr = &ora_login($lda, $statement)\fP
  918. X! Executes the given SQL statement in the database identified by $lda.
  919. X  Returns a \fIcsr\fP for use with \fIora_fetch()\fP.
  920. X  .sp
  921. X  .ti -2m
  922. X  \fB$n = &ora_fetch($csr)\fP
  923. X--- 17,31 ----
  924. X  Returns an \fIlda\fP for use with \fIora_open()\fP.
  925. X  .sp
  926. X  .ti -2m
  927. X! \fB$csr = &ora_open($lda, $statement)\fP
  928. X! Associates the given SQL statement in the database identified by $lda.
  929. X! Executes it if it contains no substitution variables.
  930. X  Returns a \fIcsr\fP for use with \fIora_fetch()\fP.
  931. X+ .sp
  932. X+ .ti -2m
  933. X+ \fB&ora_bind($csr, $var, ...)\fP
  934. X+ Binds the given values to the substition variables in the SQL statement
  935. X+ associated with $csr, and executes the resulting statement.
  936. X  .sp
  937. X  .ti -2m
  938. X  \fB$n = &ora_fetch($csr)\fP
  939. SHAR_EOF
  940. chmod 0644 Patch02 ||
  941. echo 'restore of Patch02 failed'
  942. Wc_c="`wc -c < 'Patch02'`"
  943. test 23937 -eq "$Wc_c" ||
  944.     echo 'Patch02: original size 23937, current size' "$Wc_c"
  945. fi
  946. # ============= colons.c ==============
  947. if test -f 'colons.c' -a X"$1" != X"-c"; then
  948.     echo 'x - skipping colons.c (File already exists)'
  949. else
  950. echo 'x - extracting colons.c (Text)'
  951. sed 's/^X//' << 'SHAR_EOF' > 'colons.c' &&
  952. X/* colons.c
  953. X *
  954. X * Returns the number of substitution variables in an SQL query.
  955. X */
  956. X/* Copyright 1991 Kevin Stock.
  957. X *
  958. X * You may copy this under the terms of the GNU General Public License,
  959. X * or the Artistic License, copies of which should have accompanied your
  960. X * Perl kit.
  961. X */
  962. X
  963. Xint count_colons(s)
  964. Xregister char *s;
  965. X{
  966. X    register int n = 0, c;
  967. X
  968. X    while (*s != '\0')
  969. X    {
  970. X        if (*s == ':')
  971. X        {
  972. X            /* numbers must be used in sequence,
  973. X             * but they may be repeated if a parameter is reused
  974. X             */
  975. X            if (((c = atoi(++s)) <= 0) || (c > n+1))
  976. X            {
  977. X                /* number too low or out of sequence */
  978. X                return(-1);
  979. X            }
  980. X            else if (c == n + 1)
  981. X            {
  982. X                ++n;
  983. X            }
  984. X            /* else repeating a previous parameter */
  985. X        }
  986. X        else if (*s == '\'')
  987. X        {
  988. X            while ((*++s != '\'') && (*s != '\0'))
  989. X                ;
  990. X        }
  991. X        if (*s != '\0')
  992. X        {
  993. X            ++s;
  994. X        }
  995. X    }
  996. X
  997. X    return(n);
  998. X}
  999. SHAR_EOF
  1000. chmod 0644 colons.c ||
  1001. echo 'restore of colons.c failed'
  1002. Wc_c="`wc -c < 'colons.c'`"
  1003. test 830 -eq "$Wc_c" ||
  1004.     echo 'colons.c: original size 830, current size' "$Wc_c"
  1005. fi
  1006. # ============= mkdb.pl ==============
  1007. if test -f 'mkdb.pl' -a X"$1" != X"-c"; then
  1008.     echo 'x - skipping mkdb.pl (File already exists)'
  1009. else
  1010. echo 'x - extracting mkdb.pl (Text)'
  1011. sed 's/^X//' << 'SHAR_EOF' > 'mkdb.pl' &&
  1012. X#!./oraperl
  1013. X#
  1014. X# mkdb.pl
  1015. X#
  1016. X# Sample oraperl program to create a new database and load data into it.
  1017. X#
  1018. X# Author:    Kevin Stock
  1019. X# Date:        5th August 1991
  1020. X#
  1021. X
  1022. X# let's see what oraperl is doing when it executes this
  1023. X
  1024. X$ora_debug = 136;
  1025. X
  1026. X$CREATE = "create table tryit (name char(10), ext number(3))";
  1027. X$INSERT = "insert into tryit values (:1, :2)";
  1028. X$LIST    = "select * from tryit order by name";
  1029. X$DROP    = "drop table tryit";
  1030. X
  1031. Xformat top =
  1032. X       Name         Ext
  1033. X       ====         ===
  1034. X.
  1035. X
  1036. Xformat STDOUT =
  1037. X       @<<<<<<<<<   @>>
  1038. X       $name,       $ext
  1039. X.
  1040. X
  1041. Xdie ("You should use oraperl, not perl\n") unless defined &ora_login;
  1042. X
  1043. X# create the database
  1044. X
  1045. X$lda = &ora_login("t", "kstock", "kstock")    || die $ora_errstr;
  1046. X$csr = &ora_open($lda, $CREATE)            || die $ora_errstr;
  1047. Xdo ora_close($csr)                || die $ora_errstr;
  1048. X
  1049. X# put some data into it
  1050. X
  1051. X$csr = &ora_open($lda, $INSERT)            || die $ora_errstr;
  1052. Xwhile (<DATA>)
  1053. X{
  1054. X    m/([a-z]+):([0-9]+)/;
  1055. X    do ora_bind($csr, $1, $2);
  1056. X}
  1057. Xdo ora_close($csr)                || die $ora_errstr;
  1058. X
  1059. X# list the result
  1060. X
  1061. X$csr = &ora_open($lda, $LIST)            || die $ora_errstr;
  1062. Xwhile (($name, $ext) = &ora_fetch($csr))
  1063. X{
  1064. X    write;
  1065. X}
  1066. Xdo ora_close($csr)                || die $ora_errstr;
  1067. X
  1068. X# remove the database
  1069. X
  1070. X$csr = &ora_open($lda, $DROP)            || die $ora_errstr;
  1071. Xdo ora_close($csr)                || die $ora_errstr;
  1072. Xdo ora_logoff($lda)                || die $ora_errstr;
  1073. X__END__
  1074. Xdavid:225
  1075. Xangela:208
  1076. Xbruno:302
  1077. Xalbert:294
  1078. Xjulia:292
  1079. Xalison:206
  1080. Xarnold:305
  1081. Xlarry:424
  1082. Xcatherine:201
  1083. Xrandall:306
  1084. Xsusan:307
  1085. SHAR_EOF
  1086. chmod 0755 mkdb.pl ||
  1087. echo 'restore of mkdb.pl failed'
  1088. Wc_c="`wc -c < 'mkdb.pl'`"
  1089. test 1444 -eq "$Wc_c" ||
  1090.     echo 'mkdb.pl: original size 1444, current size' "$Wc_c"
  1091. fi
  1092. exit 0
  1093.  
  1094. exit 0 # Just in case...
  1095.